package com.ehotting.edsta.csharpServer.websocket;

import com.alibaba.fastjson.JSON;
import com.ehotting.eaf.redis.configure.RedisConfig;
import com.ehotting.eaf.redis.domain.RedisMsgDto;
import com.ehotting.eaf.security.service.TokenService;
import com.ehotting.edsta.csharpServer.config.WebsocketConfigurator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RestController;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
//@RestController
@Component
@ServerEndpoint(value="/websocket.ws/{token}", configurator = WebsocketConfigurator.class)
public class WebSocketController {
 
    public static ConcurrentHashMap<String, Session> webSocketSet = new ConcurrentHashMap<>();
 
    /**
     * 与某个客户端的连接会话，需要通过它来与客户端进行数据收发
     */
    private Session session;
 
    /**
     * 用来引入刚才在webcoketConfig注入的类
     */
    @Autowired
    private RedisMessageListenerContainer container;

    @Autowired
    private TokenService tokenService;
 
    /**
     * 自定义的消息发送器
     */
    private RedisMessageListener listener;
 
    /**
     * 连接建立成功调用的方法
     * @param token
     * @param session
     * @throws Exception
     */
    @OnOpen
    public void onOpen(@PathParam("token") String token, Session session) throws Exception {
        Long userid = tokenService.getLoginUser(token).getUserid();
        log.info("userid[{}] websocket connected",userid);
//        this.session = session;
        webSocketSet.put(userid+"", session);
        listener = new RedisMessageListener();
        //放入session
        listener.setWebSocketController(this);
        container.addMessageListener(listener,
                new PatternTopic(RedisConfig.REDIS_TOPIC+userid));
    }
 
    /**
     * 连接关闭调用方法
     */
    @OnClose
    public void onClose(Session session) {
        webSocketSet.remove(session);
        log.info("websocket有一连接关闭");
        container.removeMessageListener(listener);
    }
 
    /**
     * 收到客户端消息后调用方法
     * @param message
     * @param session
     */
    @OnMessage
    public void onMessage(String message, Session session) throws Exception{
        if (session.isOpen()) {
            session.getBasicRemote().sendText(message);
        }
    }
 
    /**
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("websocket 发生异常", error);
        webSocketSet.remove(this);
        container.removeMessageListener(listener);
    }
 
    /**
     * 向客户端发送消息推送
     * @param message
     * @throws Exception
     */
    public void sendMessage(Session session,String message) throws Exception {
        synchronized (session) {
            if (session.isOpen()) {
                session.getBasicRemote().sendText(message);
            }
        }
    }

    /**
     * 向客户端发送消息推送
     * @param redisMsgDto
     * @throws Exception
     */
    public void sendMessage(RedisMsgDto<?> redisMsgDto) throws Exception {
        String userId = redisMsgDto.getUserId()+"";
        log.info("send websocket msg, userId is {}",userId);
        if(webSocketSet.get(userId) != null){
            sendMessage(webSocketSet.get(userId),redisMsgDto.getData().toString());
        }else{
            log.info("当前用户不在线：" + userId);
        }
    }
 
    /**
     * 发送信息给指定ID用户，如果用户不在线则返回
     * @param message
     * @param sendUserId
     * @throws IOException
     */
    public void sendUserMessage(String message,String sendUserId) throws Exception {
        if(webSocketSet.get(sendUserId) != null){
            sendMessage(webSocketSet.get(sendUserId),message);
        }else{
            log.info("当前用户不在线：" + sendUserId);
        }
    }
 
    /**
     * 推送信息给所有用户
     * @param message
     * @throws IOException
     */
    public void sendAllMessage(String message) throws IOException {
        for(String key : webSocketSet.keySet()){
            try {
                sendMessage(webSocketSet.get(key),message);
            }catch (Exception e){
                log.info("推送信息给所有用户异常：" + e.getMessage());
            }
        }
    }

}